package com.common.template;

import freemarker.template.Template;
import freemarker.template.utility.RichObjectWrapper;

import org.apache.commons.lang3.StringUtils;

import com.sun.crypto.provider.RSACipher;
import com.sun.media.sound.AlawCodec;

import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 描述：代码生成器 Created by Ay on 2017/5/1.
 */
public class CodeGenerateDbUtils {

	private final String AUTHOR = "parts_configs";
	private final String CURRENT_DATE = "2017/05/03";
	private final String tableName = "parts_configs";
	// private final String packageName = "com.model.SCORE_OT_RANKING";
	private final String tableAnnotation = "人员表";
	private final String URL = "jdbc:oracle:thin:@192.168.100.69:1521:ORCL";
	private final String USER = "INTEGRALSYSTEM";
	private final String PASSWORD = "INTEGRALSYSTEM123";
	private final String DRIVER = "oracle.jdbc.driver.OracleDriver";
	private final String diskPath = "D:\\workspace\\CPJFPTInterface\\src\\main\\java\\com";
	private final String changeTableName = replaceUnderLineAndUpperCase(tableName);

	public Connection getConnection() throws Exception {
		Class.forName(DRIVER);
		Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
		return connection;
	}

	public static void main(String[] args) throws Exception {
		CodeGenerateDbUtils codeGenerateUtils = new CodeGenerateDbUtils();
		codeGenerateUtils.generate();
	}

	public void generate() throws Exception {
		Connection connection = getConnection();
		try {
			Statement st = connection.createStatement();
			ResultSet rset = st.executeQuery("SELECT * FROM " + tableName + " where rownum=1");
			ResultSetMetaData md = rset.getMetaData();
			DatabaseMetaData databaseMetaData = connection.getMetaData();
			// DatabaseMetaData databaseMetaData = connection.getMetaData();
			// ResultSet resultSet = databaseMetaData.getColumns(null, "%", tableName,
			// null);
			// // 生成Mapper文件
			// generateMapperFile(resultSet);
			// 生成Dao文件
			generateDaoFile(md, databaseMetaData);
			// // 生成Repository文件
			// generateRepositoryFile(resultSet);
			// // 生成服务层接口文件
			// generateServiceInterfaceFile(resultSet);
			// // 生成服务实现层文件
			// generateServiceImplFile(resultSet);
			// // 生成Controller层文件
			// generateControllerFile(resultSet);
			// // 生成DTO文件
			// generateDTOFile(resultSet);
			// 生成Model文件
			generateModelFile(md);
			rset.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			connection.close();
		}
	}

	private void generateModelFile(ResultSetMetaData md) throws Exception {

		final String suffix = "Model.java";
		final String path = diskPath + "/model/" + tableName + suffix;
		System.out.print(path.toString());
		final String templateName = "Model.ftl";
		File mapperFile = new File(path);
		List<ColumnClass> columnClassList = new ArrayList<ColumnClass>();
		ColumnClass columnClass = null;
		for (int i = 1; i <= md.getColumnCount(); i++) {
			// while (resultSet.next()) {
			// id字段略过
			// if (resultSet.getString("COLUMN_NAME").equals("id"))
			// continue;
			columnClass = new ColumnClass();
			// 获取字段名称
			columnClass.setColumnName(md.getColumnName(i));
			// 获取字段类型
			// columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
			columnClass.setColumnTypeInt(md.getColumnType(i));
			// 转换字段名称，如 sys_name 变成 SysName
			// columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
			columnClass.setChangeColumnName(columnClass.getColumnName());
			// 字段在数据库的注释
			// columnClass.setColumnComment(resultSet.getString("REMARKS"));
			columnClass.setColumnComment(md.getColumnLabel(i));
			columnClassList.add(columnClass);
		}
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("model_column", columnClassList);
		generateFileByTemplate(templateName, mapperFile, dataMap);

	}

	private void generateDTOFile(ResultSet resultSet) throws Exception {
		final String suffix = "DTO.java";
		final String path = "D://" + changeTableName + suffix;
		final String templateName = "DTO.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateControllerFile(ResultSet resultSet) throws Exception {
		final String suffix = "Controller.java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Controller.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateServiceImplFile(ResultSet resultSet) throws Exception {
		final String suffix = "ServiceImpl.java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "ServiceImpl.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateServiceInterfaceFile(ResultSet resultSet) throws Exception {
		final String prefix = "I";
		final String suffix = "Service.java";
		final String path = diskPath + prefix + changeTableName + suffix;
		final String templateName = "ServiceInterface.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateRepositoryFile(ResultSet resultSet) throws Exception {
		final String suffix = "Repository.java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Repository.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateDaoFile(ResultSetMetaData md, DatabaseMetaData databaseMetaData) throws Exception {
		final String suffix = "DAO.java";
		final String path = diskPath + "/dao/" + tableName + suffix;
		System.out.print(path.toString());
		final String templateName = "DAO.ftl";
		File mapperFile = new File(path);
		// 获取所有字段列表及属性
		List<ColumnClass> columnClassList = new ArrayList<ColumnClass>();
		List<String> colList = new ArrayList<String>();// 为了方便找出非主键
		ColumnClass columnClass = null;
		for (int i = 1; i <= md.getColumnCount(); i++) {
			columnClass = new ColumnClass();
			columnClass.setColumnName(md.getColumnName(i));// 获取字段名称
			columnClass.setColumnTypeInt(md.getColumnType(i));// 获取字段类型 /
			columnClass.setChangeColumnName(columnClass.getColumnName());
			columnClass.setReadonly(md.isNullable(i) == 0 ? "0" : "1");
			columnClassList.add(columnClass);// 字段在数据库的注释
			colList.add(columnClass.getColumnName());
		}
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("model_column", columnClassList);
		// 获取主键及非主键列表
		List<String> priList = new ArrayList<String>();
		List<String> npriList = new ArrayList<String>();
		ResultSet rsPri = databaseMetaData.getPrimaryKeys(null, USER.toUpperCase(), tableName);
		while (rsPri.next()) {
			priList.add(rsPri.getString(4));
			if (colList.contains(rsPri.getString(4))) {
				colList.remove(rsPri.getString(4));
			}
		}
		rsPri.close();
		dataMap.put("model_pri", priList);
		dataMap.put("model_npri", colList);

		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateMapperFile(ResultSet resultSet) throws Exception {
		final String suffix = "Mapper.xml";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Mapper.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);

	}

	private void generateFileByTemplate(final String templateName, File file, Map<String, Object> dataMap)
			throws Exception {
		Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
		FileOutputStream fos = new FileOutputStream(file);
		dataMap.put("table_name_small", tableName);
		dataMap.put("table_name", tableName);
		dataMap.put("author", AUTHOR);
		dataMap.put("date", CURRENT_DATE);
		// dataMap.put("package_name", packageName);
		dataMap.put("table_annotation", tableAnnotation);
		Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
		template.process(dataMap, out);
		out.flush();
		out.close();
	}

	public String replaceUnderLineAndUpperCase(String str) {
		StringBuffer sb = new StringBuffer();
		sb.append(str);
		int count = sb.indexOf("_");
		while (count != 0) {
			int num = sb.indexOf("_", count);
			count = num + 1;
			if (num != -1) {
				char ss = sb.charAt(count);
				char ia = (char) (ss - 32);
				sb.replace(count, count + 1, ia + "");
			}
		}
		String result = sb.toString().replaceAll("_", "");
		return StringUtils.capitalize(result);
	}

}